#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <array>
#include<iostream>
class GomokuGame {
private:
    // 游戏状态枚举
    enum class GameState {
        PLAYING,
        BLACK_WIN,
        WHITE_WIN,
        DRAW
    };

    // 玩家枚举
    enum class Player {
        BLACK_,
        WHITE_
    };

    // 常量定义
    static constexpr int BOARD_SIZE = 15;
    static constexpr int CELL_SIZE = 40;
    static constexpr int MARGIN = 50;
    static constexpr int PIECE_RADIUS = 18;

    // 游戏数据
    std::array<std::array<int, BOARD_SIZE>, BOARD_SIZE> board{};
    Player currentPlayer;
    GameState gameState;

public:
    // 构造函数
    GomokuGame() : currentPlayer(Player::BLACK_), gameState(GameState::PLAYING) {
        initBoard();
    }

    // 初始化游戏
    void initBoard() {
        for (auto& row : board) {
            row.fill(0);
        }
        currentPlayer = Player::BLACK_;
        gameState = GameState::PLAYING;
    }

    // 运行游戏主循环
    void run() {
        // 创建窗口
        initGraphWindow();
        drawBoard();

        // 消息循环
        ExMessage msg;
        while (true) {
            if (peekmessage(&msg, EM_MOUSE | EM_KEY)) {
                if (msg.message == WM_LBUTTONDOWN) {
                    handleMouseClick(msg.x, msg.y);
                }
                else if (msg.message == WM_KEYDOWN) {
                    if (msg.vkcode == 'R' || msg.vkcode == 'r') {
                        initBoard();
                        drawBoard();
                    }
                }
            }
            Sleep(10);
        }
    }

private:
    // 初始化图形窗口
    void initGraphWindow() {
        initgraph(MARGIN * 2 + (BOARD_SIZE - 1) * CELL_SIZE,
                 MARGIN * 2 + (BOARD_SIZE - 1) * CELL_SIZE + 100);
    }

    // 绘制棋盘
    void drawBoard() {
        cleardevice();
        setbkcolor(RGB(220, 179, 92));
        cleardevice();

        drawGridLines();
        drawStarPoints();
        drawPieces();
        drawGameStatus();
    }

    // 绘制棋盘网格线
    void drawGridLines() {
        setlinecolor(BLACK);
        for (int i = 0; i < BOARD_SIZE; i++) {
            // 横线
            line(MARGIN, MARGIN + i * CELL_SIZE,
                 MARGIN + (BOARD_SIZE - 1) * CELL_SIZE, MARGIN + i * CELL_SIZE);
            // 竖线
            line(MARGIN + i * CELL_SIZE, MARGIN,
                 MARGIN + i * CELL_SIZE, MARGIN + (BOARD_SIZE - 1) * CELL_SIZE);
        }
    }

    // 绘制星位点
    void drawStarPoints() {
        setfillcolor(BLACK);
        const int starPoints[5][2] = {{3,3}, {11,3}, {3,11}, {11,11}, {7,7}};
        for (auto& point : starPoints) {
            fillcircle(MARGIN + point[0] * CELL_SIZE, 
                      MARGIN + point[1] * CELL_SIZE, 5);
        }
    }

    // 绘制棋子
    void drawPieces() {
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (board[i][j] == 1) {
                    drawBlackPiece(i, j);
                }
                else if (board[i][j] == 2) {
                    drawWhitePiece(i, j);
                }
            }
        }
    }

    void drawBlackPiece(int row, int col) {
        setfillcolor(BLACK);
        fillcircle(MARGIN + col * CELL_SIZE, MARGIN + row * CELL_SIZE, PIECE_RADIUS);
    }

    void drawWhitePiece(int row, int col) {
        setfillcolor(WHITE);
        fillcircle(MARGIN + col * CELL_SIZE, MARGIN + row * CELL_SIZE, PIECE_RADIUS);
        setlinecolor(BLACK);
        circle(MARGIN + col * CELL_SIZE, MARGIN + row * CELL_SIZE, PIECE_RADIUS);
    }

    // 绘制游戏状态
    void drawGameStatus() {
        settextcolor(BLACK);
        settextstyle(20, 0, _T("宋体"));
        
        const TCHAR* statusText = nullptr;
        switch (gameState) {
            case GameState::PLAYING:
                statusText = (currentPlayer == Player::BLACK_) ? 
                    _T("当前: 黑方回合") : _T("当前: 白方回合");
                break;
            case GameState::BLACK_WIN:
                statusText = _T("游戏结束: 黑方胜利!");
                break;
            case GameState::WHITE_WIN:
                statusText = _T("游戏结束: 白方胜利!");
                break;
            case GameState::DRAW:
                statusText = _T("游戏结束: 平局!");
                break;
        }
        outtextxy(MARGIN, MARGIN + BOARD_SIZE * CELL_SIZE + 20, statusText);
        outtextxy(MARGIN, MARGIN + BOARD_SIZE * CELL_SIZE + 50, _T("按R键重新开始"));
    }

    // 处理鼠标点击
    void handleMouseClick(int x, int y) {
        if (gameState != GameState::PLAYING) return;
        
        Position pos = convertToBoardPosition(x, y);
        if (isValidPosition(pos)) {
            placePiece(pos);
            updateGameState(pos);
            drawBoard();
        }
    }

    // 坐标转换
    struct Position { int row; int col; };
    
    Position convertToBoardPosition(int x, int y) {
        return {
            (y - MARGIN + CELL_SIZE / 2) / CELL_SIZE,
            (x - MARGIN + CELL_SIZE / 2) / CELL_SIZE
        };
    }

    // 检查位置是否有效
    bool isValidPosition(const Position& pos) {
        return pos.row >= 0 && pos.row < BOARD_SIZE && 
               pos.col >= 0 && pos.col < BOARD_SIZE && 
               board[pos.row][pos.col] == 0;
    }

    // 放置棋子
    void placePiece(const Position& pos) {
        board[pos.row][pos.col] = (currentPlayer == Player::BLACK_) ? 1 : 2;
    }

    // 更新游戏状态
    void updateGameState(const Position& pos) {
        if (checkWin(pos)) {
            gameState = (currentPlayer == Player::BLACK_) ? 
                GameState::BLACK_WIN : GameState::WHITE_WIN;
        }
        else if (checkDraw()) {
            gameState = GameState::DRAW;
        }
        else {
            switchPlayer();
        }
    }

    // 切换玩家
    void switchPlayer() {
        currentPlayer = (currentPlayer == Player::BLACK_) ? 
            Player::WHITE_ : Player::BLACK_;
    }

    // 检查胜利条件
    bool checkWin(const Position& pos) {
        return checkDirection(pos, 0, 1) ||  // 水平
               checkDirection(pos, 1, 0) ||  // 垂直
               checkDirection(pos, 1, 1) ||  // 对角线
               checkDirection(pos, 1, -1);   // 反对角线
    }

    // 检查特定方向
    bool checkDirection(const Position& pos, int dr, int dc) {
        const int piece = board[pos.row][pos.col];
        int count = 1;  // 当前位置已经有一个棋子

        // 正向检查
        count += countContinuousPieces(pos, dr, dc, piece);
        // 反向检查
        count += countContinuousPieces(pos, -dr, -dc, piece);

        return count >= 5;
    }

    int countContinuousPieces(const Position& start, int dr, int dc, int piece) {
        int count = 0;
        int r = start.row + dr;
        int c = start.col + dc;

        while (r >= 0 && r < BOARD_SIZE && 
               c >= 0 && c < BOARD_SIZE && 
               board[r][c] == piece) {
            count++;
            r += dr;
            c += dc;
        }
        return count;
    }

    // 检查平局
    bool checkDraw() {
        for (const auto& row : board) {
            for (int cell : row) {
                if (cell == 0) return false;
            }
        }
        return true;
    }
};

int main() {
    GomokuGame game;
    game.run();
    return 0;
}
